package utils

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"tuiwen-go/internal/config"
)

// GenerateAudioWithEdgeTTS generates audio from text using edge-tts and saves it to a file.
// GenerateAudioWithEdgeTTS 使用 edge-tts 从文本生成音频并保存到文件。
// It returns the relative path to the saved audio file and an error, if any.
// 它返回保存的音频文件的相对路径和任何错误。
func GenerateAudioWithEdgeTTS(text, voice, outputDir string) (string, error) {
	if err := os.MkdirAll(outputDir, 0755); err != nil {
		return "", fmt.Errorf("failed to create output directory: %w", err)
	}

	if voice == "" {
		voice = "zh-CN-YunxiNeural"
	}
	// Generate a unique filename for the audio file
	// 为音频文件生成一个唯一的文件名
	audioFileName := fmt.Sprintf("audio_%d.mp3", generateUniqueId())
	audioFilePath := filepath.Join(outputDir, audioFileName)

	args := []string{"--text", text, "--write-media", audioFilePath}

	args = append(args, "--voice", voice)

	args = append(args, "--rate", "+0%")

	args = append(args, "--pitch", "+0Hz")

	// edge-tts volume parameter expects a relative value like +0% or -10%
	// If the volume is 100 (default from frontend), it means +0% change.
	// Otherwise, we assume the frontend sends a value that can be directly used or converted.

	// Assuming frontend sends a value that can be directly used by edge-tts if not 100
	// For example, if frontend sends "+10%" or "-5%"

	// If volume is 100, it means no change from default, which is +0% for edge-tts
	args = append(args, "--volume", "+0%")

	// Command to execute edge-tts
	// 执行 edge-tts 的命令
	cmd := exec.Command(config.LoadedConfig.EdgeTTSPath, args...)

	cmd.Stderr = os.Stderr // Redirect stderr to see edge-tts errors

	// Log the full command being executed
	log.Printf("Executing command: %s %v", config.LoadedConfig.EdgeTTSPath, args)

	err := cmd.Run()
	if err != nil {
		log.Printf("Error running edge-tts: %v", err)
		return "", fmt.Errorf("Error running edge-tts: %v", err)
	}

	log.Printf("成功生成音频: %s", audioFilePath)
	return audioFilePath, nil
}

// generateUniqueId is a placeholder for generating a unique ID. In a real application,
// generateUniqueId 是一个生成唯一 ID 的占位符。在实际应用中，
func generateUniqueId() int64 {
	return NowUnixNano()
}

// NowUnixNano returns the current Unix timestamp in nanoseconds.
// NowUnixNano 返回当前 Unix 时间戳（纳秒）。
func NowUnixNano() int64 {
	return Now().UnixNano()
}

// Now returns the current local time.
// Now 返回当前本地时间。
func Now() time.Time {
	return time.Now()
}

// DeleteFile deletes a file from the given path.
// DeleteFile 从给定路径删除文件。
func DeleteFile(filePath string) error {
	err := os.Remove(filePath)
	if err != nil {
		if os.IsNotExist(err) {
			return nil // File doesn't exist, nothing to do
		}
		return fmt.Errorf("failed to delete file %s: %w", filePath, err)
	}
	return nil
}

// GetAudioDuration 获取音频文件的时长（秒）。
func GetAudioDuration(audioFilePath string) (float64, error) {
	// 使用ffprobe命令获取音频文件时长
	cmd := exec.Command("ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", audioFilePath)

	var out bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = os.Stderr

	err := cmd.Run()
	if err != nil {
		return 0, fmt.Errorf("failed to run ffprobe: %w", err)
	}

	// 解析输出获取时长
	durationStr := strings.TrimSpace(out.String())
	duration, err := strconv.ParseFloat(durationStr, 64)
	if err != nil {
		return 0, fmt.Errorf("failed to parse duration: %w", err)
	}

	return duration * 1000000, nil
}
